GLOBAL  _read_msw,_lidt

GLOBAL  _mascaraPIC1,_mascaraPIC2,_Cli,_Sti
GLOBAL  _debug
GLOBAL  _int_20_hand,_int_21_hand,_int_80_hand
GLOBAL	_set_pic_int
GLOBAL	_read_key
GLOBAL	_inport
GlOBAL  _outport
GLOBAL	_sgdt
GLOBAL	_lgdt
GLOBAL _actual_PL
GLOBAL _pruebaTimer
GLOBAL _int_40_hand
GLOBAL _int_32_hand
GLOBAL _enable_mouse
GLOBAL _timerTick

EXTERN	__read
EXTERN	__write
EXTERN  int_21
EXTERN	int_20
EXTERN	int_32
EXTERN 	leomouse
EXTERN int_2c



WRITE	equ 0
READ	equ 1

SECTION .text


_Cli:
	cli			; limpia flag de interrupciones
	ret

_Sti:

	sti			; habilita interrupciones por flag
	ret

; Habilita al mouse  para empezar a recibir sus interrupciones
_enable_mouse:
	call	mouseWait2	; espero para poder enviar datos al mouse.
	mov	al,0A8h
	out	64h,al		; activo el dispositivo auxiliar del mouse.
	
	call	mouseWait2	; espero para poder enviar datos al mouse.
	mov	al,20h
	out	64h,al 		; envio 20h al puerto 64h para que el mouse mande el byte de estado

	call	mouseWait1	; espero para poder recibir datos del mouse.
	in	al,60h		; recibo el byte de estado del mouse
	mov	ah,al
	or	ah,2		; habilito al mouse para que mande interrupciones

	call	mouseWait2 	; espero para poder enviar datos al mouse.
	mov	al,60h
	out	64h,al		; envio 60h al puerto 64h para avisar que se va a enviar el byte de estado de nuevo.

	call	mouseWait2 	; espero para poder enviar datos al mouse.
	mov	al,ah
	out     60h,al		; envio el byte de estado.
		
	call	mouseWait2 	; espero para poder enviar datos al mouse.
	mov	al,0D4h	
	out	64h,al		; envio D4h al puerto 64h para decirle al mouse que se va a enviar un comando.
	call	mouseWait2 	; espero para poder enviar datos al mouse.
	mov	al,0F6h		
	out	60h,al		; envio el comando de cargar la configuracion default del mouse.
	
	call	mouseWait1	; espero para poder recibir datos del mouse.
	in	al,60h

	call	mouseWait2	 ; espero para poder enviar datos al mouse.
	mov	al,0D4h
	out	64h,al		; envio D4h al puerto 64h para decirle al mouse que se va a enviar un comando.
	call	mouseWait2 	; espero para poder enviar datos al mouse.
	mov	al,0F4h		
	out	60h,al		; habilito el mouse
	
	call	mouseWait1	; espero para poder recibir datos del mouse.
	in	al,60h

	ret
	
	
; Espera para poder recibir datos del mouse, tiene un timeout por si no se recibe nada.	
mouseWait1:
	push	ecx
	push	eax
	mov	ecx,100000
	
ciclo1:	
	in	al,64h
	and	al,1
	cmp	al,1		; si recibe un 1 en el primer bit puedo recibir datos
	jz	mwait1_end
	dec	ecx		; si no recibe un 0 en el segundo bit, decremento el timer,
	jnz	ciclo1		; asi no queda en un ciclo infinito.

mwait1_end:
	pop	eax
	pop	ecx
	ret

; Espera para poder enviar datos al mouse, tiene un timeout por si no se recibe nada.
mouseWait2:
	push	ecx
	push	eax
	mov	ecx,100000
	
ciclo2:	
	in	al,64h		
	and	al,2		; si recibe un 0 en el segundo bit puedo enviar datos
	cmp	al,0		
	jz	mwait2_end	
	dec	ecx		; si no recibe un 0 en el segundo bit, decremento el timer,
	jnz	ciclo2		; asi no queda en un ciclo infinito.

mwait2_end:
	pop	eax
	pop	ecx
	ret


_int_40_hand:
	push    ebp
        mov     ebp, esp
	mov 	ebx, 1
	push	ebx			
	call	__write
	pop 	ebp
	ret

_pruebaTimer:
	push    ebp
        mov     ebp, esp
	xor 	ax, ax
	mov	es, ax
	mov	eax, [0x046C]
;	sub	eax, 0FFFFFFFFh
	mov	[0x046C], eax
	pop 	ebp
	ret
	
_timerTick:
	push    ebp
        mov     ebp, esp
	mov	cx,[ebp+8]
	
        cli
        mov  al,00110110b  ; bit 7,6 = (00) timer counter 0
                             ; bit 5,4 = (11) write LSB then MSB
                             ; bit 3-1 = (011) generate square wave
                             ; bit 0 = (0) binary counter
        out  43h,al        ; prep PIT, counter 0, square wave&init count
        jmp  _tt2
_tt2:	nop
        ;mov  cx,timer  	; default is 0x0000 (65536) (18.2 per sec)
                             ; interrupts when counter decrements to 0
      	;mov cx, 0x01

        mov  al,cl         ; send LSB of timer count
       	out  40h,al
        jmp  _tt3
_tt3:	nop
      	 mov  al,ch         ; send MSB of timer count
       	out  40h,al
        jmp  _tt4
_tt4:	nop
        sti
	mov	esp,ebp	
	pop 	ebp
	mov	ax,cx
	ret
  

_mascaraPIC1:			; Escribe mascara del PIC 1
	push    ebp
        mov     ebp, esp
        mov     ax, [ss:ebp+8]  ; ax = mascara de 16 bits
        out	21h,al
        pop     ebp
        retn

_mascaraPIC2:			; Escribe mascara del PIC 2
	push    ebp
        mov     ebp, esp
        mov     ax, [ss:ebp+8]  ; ax = mascara de 16 bits
        out	0A1h,al
        pop     ebp
        retn

_read_msw:
        smsw    ax		; Obtiene la Machine Status Word
        retn


_lidt:				; Carga el IDTR
        push    ebp
        mov     ebp, esp
        push    ebx
	mov 	ebx, [ss: ebp + 8]
        ;mov     ebx, [ss: ebp + 6] ; ds:bx = puntero a IDTR 
	;rol	ebx,16
	lidt    [ds: ebx]          ; carga IDTR
        pop     ebx
        pop     ebp
        retn

_lgdt:				; Carga el GDTR
        push    ebp
        mov     ebp, esp
        push    ebx
	mov 	ebx, [ss: ebp + 8]
        ;mov     ebx, [ss: ebp + 6] ; ds:bx = puntero a IDTR 
	;rol	ebx,16
	lgdt    [ds: ebx]          ; carga GDTR
        pop     ebx
        pop     ebp
        retn
_sgdt:				; Carga el GDTR
        push    ebp
        mov     ebp, esp
        push    ebx
	mov 	ebx, [ss: ebp + 8]
        ;mov     ebx, [ss: ebp + 6] ; ds:bx = puntero a GDTR 
	;rol	ebx,16
	sgdt	[ds: ebx]          ; retorno en ax la posicion de memoria donde empieza la gdt
        pop     ebx
        pop     ebp
        retn


_int_80_hand:
	push 	ebp
	mov	ebp,esp
	;and	esp,-16
_write:
	cmp	eax,WRITE
	jnz	_read
	push	edx			;tercer parametro de write
	push	ecx			;segundo parametro de write
	push	ebx			;primer parametro del afuncion write
	call	__write
	add	esp,12			;resto 12 para sacar los 3 parametros de la pila
	jmp	_int_80_ret
_read:
	cmp	eax,READ
	jnz	_int_80_ret
	push	edx			;tercer parametro de write
	push	ecx			;segundo parametro de write
	push	ebx			;primer parametro del afuncion write
	call	__read
	add	esp,12
_int_80_ret:
	leave
	iret

_int_21_hand:				; Handler de INT 33 ( Interrupcion de teclado)

	push    ebp
        mov     ebp, esp
        push    ds
        push    es                      ; Se salvan los registros
        pusha				; Carga de DS y ES con el valor del selector
 	mov     ax, 10h			; a utilizar.
        mov     ds, ax
        mov     es, ax
	call    int_21 
        mov	al,20h			; Envio de EOI generico al PIC
	out	20h,al 
	popa                         
        pop     es
        pop     ds
	mov 	esp, ebp
	pop 	ebp
        iret
_outport:
	push 	ebp
	mov		ebp, esp
	mov 	dx, [ss:ebp+8]
	mov 	al, [ss:ebp+12]
	out 	dx, al
	mov 	esp, ebp
	pop 	ebp
	ret

_inport:
	push 	ebp
	mov	ebp, esp
	mov	dx, [ss:ebp+8]
	in	al,dx
	mov 	esp, ebp
	pop 	ebp
	ret	
_int_20_hand:
	push 	ebp
	mov	ebp, esp			; Handler de INT 8 ( Timer tick)
        push    ds
        push    es                      ; Se salvan los registros
        pusha                           ; Carga de DS y ES con el valor del selector
        mov     ax, 10h			; a utilizar.
        mov     ds, ax
        mov     es, ax                  
        call    int_20                 
        mov	al,20h			; Envio de EOI generico al PIC
	out	20h,al
	popa                            
        pop     es
        pop     ds
	mov 	esp, ebp
	pop 	ebp
        iret

_set_pic_int:

      	ICW1	equ	0x11	;inicializo el pic , icw4 necesario, cascade mode, edge triggered mode
	ICW2	equ	0x20	;muevo el vector de interrupciones del pic1 33 lugares para abajo
	ICW3	equ	0x04	;le digo que voy a clgar el slave en la irq2
	ICW4	equ	0x01	;non buffered 8086/8088 mode, eoi normal not special fully nested mode
	ICW2S	equ	0x28	;muevo el vetro de interrupcione del pic2
	ICW3S	equ	0x02	;le digo al salve en donde esta conectado(irq2)

;Paso a setear el pic1(master)                            
	mov     al,ICW1       
	out     20h,al         
	mov     al,ICW2            
	out     21h,al         
	mov     al,ICW3          
	out     21h,al         
	mov     al,ICW4 
	out     21h,al         

;Paso a setear el pic2(salave)
	mov     al,ICW1      
	out     0A0h,al         
	mov     al,ICW2S         
	out     0A1h,al         
	mov     al,ICW3S           
	out     0A1h,al         
	mov     al,ICW4            
	out     0A1h,al
     
	retn

; Debug para el BOCHS, detiene la ejecució; Para continuar colocar en el BOCHSDBG: set $eax=0
;


_debug:
        push    bp
        mov     bp, sp
        push	ax
vuelve:	mov     ax, 1
        cmp	ax, 0
	jne	vuelve
	pop	ax
	pop     bp
        retn

;Handler de la interrupcion 2C, del MOUSE
_int_32_hand:

	push	ebp
	mov	ebp,esp
	pusha
      
	mov	eax,0
	in	al,60h			; leo del puerto 60h
	mov	ah,00h
	
	push	eax
      	call 	_Cli
	call	leomouse
	call 	_Sti
	add	esp,4
	
	mov	al,20h			
	out	0A0h,al			; Envio de EOI generico al PIC2
	
	out	20h,al			; Envio de EOI generico al PIC1
      
	popa
	mov	esp,ebp
	pop	ebp
	iret



